From f54e7712c53f914dc1bd04b7ebaaef30dc2ce86c Mon Sep 17 00:00:00 2001 From: Carlos Soriano Date: Mon, 30 Oct 2017 21:38:41 +0100 Subject: [PATCH] gtkplacessidebar: Adapt to libcloudproviders 0.2.x And a few improvements on the way. https://bugzilla.gnome.org/show_bug.cgi?id=786123 --- gtk/gtkplacessidebar.c | 264 +++++++++++++++++++++++------------------ gtk/gtksidebarrow.c | 90 +++++++++++--- meson.build | 2 +- 3 files changed, 227 insertions(+), 129 deletions(-) diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c index 09e8f3574f..92b380696d 100644 --- a/gtk/gtkplacessidebar.c +++ b/gtk/gtkplacessidebar.c @@ -25,8 +25,9 @@ #include #ifdef HAVE_CLOUDPROVIDERS -#include -#include +#include +#include +#include #endif #include "gtkplacessidebarprivate.h" @@ -127,8 +128,8 @@ struct _GtkPlacesSidebar { GtkBookmarksManager *bookmarks_manager; #ifdef HAVE_CLOUDPROVIDERS - CloudProviders *cloud_manager; - GList *cloud_rows; + CloudProvidersCollector *cloud_manager; + GList *unready_accounts; #endif GVolumeMonitor *volume_monitor; @@ -458,7 +459,7 @@ add_place (GtkPlacesSidebar *sidebar, GVolume *volume, GMount *mount, #ifdef HAVE_CLOUDPROVIDERS - CloudProviderAccount *cloud_provider_account, + CloudProvidersAccount *cloud_provider_account, #else gpointer *cloud_provider_account, #endif @@ -493,7 +494,7 @@ add_place (GtkPlacesSidebar *sidebar, "volume", volume, "mount", mount, #ifdef HAVE_CLOUDPROVIDERS - "cloud-provider", cloud_provider_account, + "cloud-provider-account", cloud_provider_account, #endif NULL); @@ -914,61 +915,80 @@ update_trash_icon (GtkPlacesSidebar *sidebar) } #ifdef HAVE_CLOUDPROVIDERS -static void -cloud_row_update (CloudProviderAccount *cloud_provider_account, - GtkWidget *cloud_row) + +static gboolean +create_cloud_provider_account_row (GtkPlacesSidebar *sidebar, + CloudProvidersAccount *account) { GIcon *end_icon; - gint provider_status; - provider_status = cloud_provider_account_get_status (cloud_provider_account); - switch (provider_status) + GIcon *start_icon; + gchar *mount_uri; + gchar *name; + gchar *tooltip; + guint provider_account_status; + + start_icon = cloud_providers_account_get_icon (account); + name = cloud_providers_account_get_name (account); + provider_account_status = cloud_providers_account_get_status (account); + mount_uri = cloud_providers_account_get_path (account); + if (start_icon != NULL + && name != NULL + && provider_account_status != CLOUD_PROVIDERS_ACCOUNT_STATUS_INVALID + && mount_uri != NULL) { - case CLOUD_PROVIDER_STATUS_IDLE: - end_icon = NULL; - break; + switch (provider_account_status) + { + case CLOUD_PROVIDERS_ACCOUNT_STATUS_IDLE: + end_icon = NULL; + break; - case CLOUD_PROVIDER_STATUS_SYNCING: - end_icon = g_themed_icon_new ("emblem-synchronizing-symbolic"); - break; + case CLOUD_PROVIDERS_ACCOUNT_STATUS_SYNCING: + end_icon = g_themed_icon_new ("emblem-synchronizing-symbolic"); + break; - case CLOUD_PROVIDER_STATUS_ERROR: - end_icon = g_themed_icon_new ("dialog-warning-symbolic"); - break; + case CLOUD_PROVIDERS_ACCOUNT_STATUS_ERROR: + end_icon = g_themed_icon_new ("dialog-warning-symbolic"); + break; - default: - return; - } + default: + return FALSE; + } - gtk_sidebar_row_set_end_icon (GTK_SIDEBAR_ROW (cloud_row), end_icon); - if (end_icon != NULL) - g_object_unref (end_icon); + mount_uri = g_strconcat ("file://", mount_uri, NULL); - g_object_set (cloud_row, - "label", cloud_provider_account_get_name (cloud_provider_account), - NULL); - g_object_set (cloud_row, - "tooltip", cloud_provider_account_get_status_details (cloud_provider_account), - NULL); + /* translators: %s is the name of a cloud provider for files */ + tooltip = g_strdup_printf (_("Open %s"), name); -} + add_place (sidebar, PLACES_BUILT_IN, + SECTION_CLOUD, + name, start_icon, end_icon, mount_uri, + NULL, NULL, NULL, account, 0, + tooltip); -void -cloud_row_destroy (GtkWidget *object, - gpointer user_data) -{ - GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data); - CloudProviderAccount *cloud_provider_account = NULL; - g_object_get (GTK_SIDEBAR_ROW (object), "cloud-provider", &cloud_provider_account, NULL); - if (cloud_provider_account != NULL) + return TRUE; + } + else { - g_signal_handlers_disconnect_matched (cloud_provider_account, - G_SIGNAL_MATCH_DATA, - 0, 0, 0, cloud_row_update, object); - g_object_unref (object); - g_object_unref (cloud_provider_account); + return FALSE; } - sidebar->cloud_rows = g_list_remove (sidebar->cloud_rows, object); } + +static void +on_account_updated (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + CloudProvidersAccount *account = CLOUD_PROVIDERS_ACCOUNT (object); + GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data); + + if (create_cloud_provider_account_row (sidebar, account)) + { + g_signal_handlers_disconnect_by_data (account, sidebar); + sidebar->unready_accounts = g_list_remove (sidebar->unready_accounts, account); + g_object_unref (account); + } +} + #endif static void @@ -991,10 +1011,10 @@ update_places (GtkPlacesSidebar *sidebar) GList *network_mounts, *network_volumes; GIcon *new_bookmark_icon; #ifdef HAVE_CLOUDPROVIDERS - GIcon *end_icon; - GList *cloud_provider_proxies; - guint provider_status; - gchar *cloudprovider_path; + GList *cloud_providers; + GList *cloud_providers_accounts; + CloudProvidersAccount *cloud_provider_account; + CloudProvidersProvider *cloud_provider; #endif GtkStyleContext *context; @@ -1103,52 +1123,39 @@ update_places (GtkPlacesSidebar *sidebar) /* Cloud providers */ #ifdef HAVE_CLOUDPROVIDERS - cloud_provider_proxies = cloud_providers_get_providers (sidebar->cloud_manager); - for (l = cloud_provider_proxies; l != NULL; l = l->next) + cloud_providers = cloud_providers_collector_get_providers (sidebar->cloud_manager); + for (l = sidebar->unready_accounts; l != NULL; l = l->next) { - start_icon = cloud_provider_account_get_icon (l->data); - name = cloud_provider_account_get_name (l->data); - provider_status = cloud_provider_account_get_status (l->data); - cloudprovider_path = cloud_provider_account_get_path (l->data); - if (start_icon == NULL - || name == NULL - || provider_status == CLOUD_PROVIDER_STATUS_INVALID - || cloudprovider_path == NULL) - continue; - cloudprovider_path = g_strconcat ("file://", cloud_provider_account_get_path (l->data), NULL); - switch (provider_status) + g_signal_handlers_disconnect_by_data (l->data, sidebar); + } + g_list_free_full (sidebar->unready_accounts, g_object_unref); + sidebar->unready_accounts = NULL; + for (l = cloud_providers; l != NULL; l = l->next) + { + cloud_provider = CLOUD_PROVIDERS_PROVIDER (l->data); + g_signal_connect_swapped (cloud_provider, "accounts-changed", + G_CALLBACK (update_places), sidebar); + cloud_providers_accounts = cloud_providers_provider_get_accounts (cloud_provider); + for (ll = cloud_providers_accounts; ll != NULL; ll = ll->next) { - case CLOUD_PROVIDER_STATUS_IDLE: - end_icon = NULL; - break; - - case CLOUD_PROVIDER_STATUS_SYNCING: - end_icon = g_themed_icon_new ("emblem-synchronizing-symbolic"); - break; + cloud_provider_account = CLOUD_PROVIDERS_ACCOUNT (ll->data); + if (!create_cloud_provider_account_row (sidebar, cloud_provider_account)) + { - case CLOUD_PROVIDER_STATUS_ERROR: - end_icon = g_themed_icon_new ("dialog-warning-symbolic"); - break; + g_signal_connect (cloud_provider_account, "notify::name", + G_CALLBACK (on_account_updated), sidebar); + g_signal_connect (cloud_provider_account, "notify::status", + G_CALLBACK (on_account_updated), sidebar); + g_signal_connect (cloud_provider_account, "notify::status-details", + G_CALLBACK (on_account_updated), sidebar); + g_signal_connect (cloud_provider_account, "notify::path", + G_CALLBACK (on_account_updated), sidebar); + sidebar->unready_accounts = g_list_append (sidebar->unready_accounts, + g_object_ref (cloud_provider_account)); + continue; + } - default: - continue; } - - /* translators: %s is the name of a cloud provider for files */ - tooltip = g_strdup_printf (_("Open %s"), name); - - GtkWidget *cloud_row = NULL; - cloud_row = add_place (sidebar, PLACES_BUILT_IN, - SECTION_CLOUD, - name, start_icon, end_icon, cloudprovider_path, - NULL, NULL, NULL, l->data, 0, - tooltip); - - g_signal_connect (l->data, "changed", G_CALLBACK (cloud_row_update), cloud_row); - g_signal_connect (cloud_row, "destroy", G_CALLBACK (cloud_row_destroy), sidebar); - g_object_ref (cloud_row); - g_object_ref (l->data); - sidebar->cloud_rows = g_list_append (sidebar->cloud_rows, cloud_row); } #endif @@ -3542,17 +3549,17 @@ on_row_popover_destroy (GtkWidget *row_popover, static void build_popup_menu_using_gmenu (GtkSidebarRow *row) { - CloudProviderAccount *cloud_provider_account; + CloudProvidersAccount *cloud_provider_account; GtkPlacesSidebar *sidebar; GMenuModel *cloud_provider_menu; GActionGroup *cloud_provider_action_group; g_object_get (row, "sidebar", &sidebar, - "cloud-provider", &cloud_provider_account, + "cloud-provider-account", &cloud_provider_account, NULL); - /* Cloud provider */ + /* Cloud provider account */ if (cloud_provider_account) { GMenu *menu = g_menu_new (); @@ -3569,19 +3576,23 @@ build_popup_menu_using_gmenu (GtkSidebarRow *row) g_menu_item_set_action_and_target_value (item, "row.open-other", g_variant_new_int32 (GTK_PLACES_OPEN_NEW_WINDOW)); g_menu_append_item (menu, item); - cloud_provider_menu = cloud_provider_account_get_menu_model (cloud_provider_account); - g_menu_append_section (menu, NULL, cloud_provider_menu); - cloud_provider_action_group = cloud_provider_account_get_action_group (cloud_provider_account); - gtk_widget_insert_action_group (GTK_WIDGET (sidebar), - "cloudprovider", - G_ACTION_GROUP (cloud_provider_action_group)); + cloud_provider_menu = cloud_providers_account_get_menu_model (cloud_provider_account); + cloud_provider_action_group = cloud_providers_account_get_action_group (cloud_provider_account); + if (cloud_provider_menu != NULL && cloud_provider_action_group != NULL) + { + g_menu_append_section (menu, NULL, cloud_provider_menu); + gtk_widget_insert_action_group (GTK_WIDGET (sidebar), + "cloudprovider", + G_ACTION_GROUP (cloud_provider_action_group)); + } add_actions (sidebar); if (sidebar->popover) gtk_widget_destroy (sidebar->popover); sidebar->popover = gtk_popover_new_from_model (GTK_WIDGET (sidebar), G_MENU_MODEL (menu)); - g_signal_connect (sidebar->popover, "destroy", G_CALLBACK (on_row_popover_destroy), sidebar); + g_signal_connect (sidebar->popover, "destroy", + G_CALLBACK (on_row_popover_destroy), sidebar); g_object_unref (sidebar); g_object_unref (cloud_provider_account); } @@ -3597,15 +3608,15 @@ create_row_popover (GtkPlacesSidebar *sidebar, GtkWidget *box; #ifdef HAVE_CLOUDPROVIDERS - CloudProviderAccount *cloud_provider_account; + CloudProvidersAccount *cloud_provider_account; - g_object_get (row, "cloud-provider", &cloud_provider_account, NULL); + g_object_get (row, "cloud-provider-account", &cloud_provider_account, NULL); if (cloud_provider_account) - { - build_popup_menu_using_gmenu (row); - return; - } + { + build_popup_menu_using_gmenu (row); + return; + } #endif sidebar->popover = gtk_popover_new (GTK_WIDGET (sidebar)); @@ -4112,13 +4123,11 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar) /* Cloud providers */ #ifdef HAVE_CLOUDPROVIDERS - sidebar->cloud_rows = NULL; - sidebar->cloud_manager = cloud_providers_dup_singleton (); + sidebar->cloud_manager = cloud_providers_collector_dup_singleton (); g_signal_connect_swapped (sidebar->cloud_manager, - "owners-changed", + "providers-changed", G_CALLBACK (update_places), sidebar); - cloud_providers_update (sidebar->cloud_manager); #endif /* populate the sidebar */ @@ -4247,6 +4256,9 @@ static void gtk_places_sidebar_dispose (GObject *object) { GtkPlacesSidebar *sidebar; +#ifdef HAVE_CLOUDPROVIDERS + GList *l; +#endif sidebar = GTK_PLACES_SIDEBAR (object); @@ -4332,12 +4344,35 @@ gtk_places_sidebar_dispose (GObject *object) sidebar->shortcuts = NULL; #ifdef HAVE_CLOUDPROVIDERS - g_clear_object (&sidebar->cloud_manager); + for (l = cloud_providers_collector_get_providers (sidebar->cloud_manager); + l != NULL; l = l->next) + { + g_signal_handlers_disconnect_by_data (l->data, sidebar); + } + for (l = sidebar->unready_accounts; l != NULL; l = l->next) + { + g_signal_handlers_disconnect_by_data (l->data, sidebar); + } + g_list_free_full (sidebar->unready_accounts, g_object_unref); + sidebar->unready_accounts = NULL; #endif G_OBJECT_CLASS (gtk_places_sidebar_parent_class)->dispose (object); } +static void +gtk_places_sidebar_finalize (GObject *object) +{ + GtkPlacesSidebar *sidebar; + + sidebar = GTK_PLACES_SIDEBAR (object); +#ifdef HAVE_CLOUDPROVIDERS + g_clear_object (&sidebar->cloud_manager); +#endif + + G_OBJECT_CLASS (gtk_places_sidebar_parent_class)->finalize (object); +} + static void gtk_places_sidebar_class_init (GtkPlacesSidebarClass *class) { @@ -4346,6 +4381,7 @@ gtk_places_sidebar_class_init (GtkPlacesSidebarClass *class) gobject_class->dispose = gtk_places_sidebar_dispose; + gobject_class->finalize = gtk_places_sidebar_finalize; gobject_class->set_property = gtk_places_sidebar_set_property; gobject_class->get_property = gtk_places_sidebar_get_property; diff --git a/gtk/gtksidebarrow.c b/gtk/gtksidebarrow.c index 65a69f5048..26bce9b3b6 100644 --- a/gtk/gtksidebarrow.c +++ b/gtk/gtksidebarrow.c @@ -30,7 +30,7 @@ #include "gtkselection.h" #ifdef HAVE_CLOUDPROVIDERS -#include +#include #endif struct _GtkSidebarRow @@ -52,7 +52,7 @@ struct _GtkSidebarRow GDrive *drive; GVolume *volume; GMount *mount; - GObject *cloud_provider; + GObject *cloud_provider_account; gboolean placeholder; GtkPlacesSidebar *sidebar; GtkWidget *revealer; @@ -76,13 +76,58 @@ enum PROP_DRIVE, PROP_VOLUME, PROP_MOUNT, - PROP_CLOUD_PROVIDER, + PROP_CLOUD_PROVIDER_ACCOUNT, PROP_PLACEHOLDER, LAST_PROP }; static GParamSpec *properties [LAST_PROP]; +#ifdef HAVE_CLOUDPROVIDERS + +static void +cloud_row_update (GtkSidebarRow *self) +{ + CloudProvidersAccount *account; + GIcon *end_icon; + gint provider_status; + + account = CLOUD_PROVIDERS_ACCOUNT (self->cloud_provider_account); + provider_status = cloud_providers_account_get_status (account); + switch (provider_status) + { + case CLOUD_PROVIDERS_ACCOUNT_STATUS_IDLE: + end_icon = NULL; + break; + + case CLOUD_PROVIDERS_ACCOUNT_STATUS_SYNCING: + end_icon = g_themed_icon_new ("emblem-synchronizing-symbolic"); + break; + + case CLOUD_PROVIDERS_ACCOUNT_STATUS_ERROR: + end_icon = g_themed_icon_new ("dialog-warning-symbolic"); + break; + + default: + return; + } + + g_object_set (self, + "label", cloud_providers_account_get_name (account), + NULL); + g_object_set (self, + "tooltip", cloud_providers_account_get_status_details (account), + NULL); + g_object_set (self, + "end-icon", end_icon, + NULL); + + if (end_icon != NULL) + g_object_unref (end_icon); +} + +#endif + static void gtk_sidebar_row_get_property (GObject *object, guint prop_id, @@ -145,8 +190,8 @@ gtk_sidebar_row_get_property (GObject *object, g_value_set_object (value, self->mount); break; - case PROP_CLOUD_PROVIDER: - g_value_set_object (value, self->cloud_provider); + case PROP_CLOUD_PROVIDER_ACCOUNT: + g_value_set_object (value, self->cloud_provider_account); break; case PROP_PLACEHOLDER: @@ -265,9 +310,22 @@ gtk_sidebar_row_set_property (GObject *object, g_set_object (&self->mount, g_value_get_object (value)); break; - case PROP_CLOUD_PROVIDER: + case PROP_CLOUD_PROVIDER_ACCOUNT: #ifdef HAVE_CLOUDPROVIDERS - g_set_object (&self->cloud_provider, g_value_get_object (value)); + if (self->cloud_provider_account != NULL) + g_signal_handlers_disconnect_by_data (self->cloud_provider_account, self); + + self->cloud_provider_account = g_value_dup_object (value); + + if (self->cloud_provider_account != NULL) + { + g_signal_connect_swapped (self->cloud_provider_account, "notify::name", + G_CALLBACK (cloud_row_update), self); + g_signal_connect_swapped (self->cloud_provider_account, "notify::status", + G_CALLBACK (cloud_row_update), self); + g_signal_connect_swapped (self->cloud_provider_account, "notify::status-details", + G_CALLBACK (cloud_row_update), self); + } #endif break; @@ -291,7 +349,7 @@ gtk_sidebar_row_set_property (GObject *object, g_clear_object (&self->drive); g_clear_object (&self->volume); g_clear_object (&self->mount); - g_clear_object (&self->cloud_provider); + g_clear_object (&self->cloud_provider_account); gtk_container_foreach (GTK_CONTAINER (self), (GtkCallback) gtk_widget_destroy, @@ -398,7 +456,11 @@ gtk_sidebar_row_finalize (GObject *object) g_clear_object (&self->drive); g_clear_object (&self->volume); g_clear_object (&self->mount); - g_clear_object (&self->cloud_provider); +#ifdef HAVE_CLOUDPROVIDERS + if (self->cloud_provider_account != NULL) + g_signal_handlers_disconnect_by_data (self->cloud_provider_account, self); + g_clear_object (&self->cloud_provider_account); +#endif G_OBJECT_CLASS (gtk_sidebar_row_parent_class)->finalize (object); } @@ -530,10 +592,10 @@ gtk_sidebar_row_class_init (GtkSidebarRowClass *klass) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - properties [PROP_CLOUD_PROVIDER] = - g_param_spec_object ("cloud-provider", - "CloudProviderAccount", - "CloudProviderAccount", + properties [PROP_CLOUD_PROVIDER_ACCOUNT] = + g_param_spec_object ("cloud-provider-account", + "CloudProvidersAccount", + "CloudProvidersAccount", G_TYPE_OBJECT, (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); @@ -579,7 +641,7 @@ gtk_sidebar_row_clone (GtkSidebarRow *self) "drive", self->drive, "volume", self->volume, "mount", self->mount, - "cloud-provider", self->cloud_provider, + "cloud-provider-account", self->cloud_provider_account, NULL); } diff --git a/meson.build b/meson.build index fc5bf96ecb..1288caa8e0 100644 --- a/meson.build +++ b/meson.build @@ -38,7 +38,7 @@ mirclient_req = '>= 0.22.0' mircookie_req = '>= 0.17.0' graphene_req = '>= 1.5.1' epoxy_req = '>= 1.4' -cloudproviders_req = '>= 0.2.0' +cloudproviders_req = '>= 0.2.5' xkbcommon_req = '>= 0.2.0' gnome = import('gnome') -- 2.30.2